﻿using System;
using System.IO;
using System.Linq;
using LINQPad.Extensibility.DataContext;
using LINQPad.OpenAccess.Data;
using LINQPad.OpenAccess.Helpers;
using LINQPad.OpenAccess.Settings;

namespace LINQPad.OpenAccess.Services.Descriptors
{
    /// <summary>
    ///   <see cref="IConnectionDescriptor" /> for predefined connections.
    /// </summary>
    public class PredefinedConnectionDescriptor : DefaultConnectionDescriptor
    {
        #region Private

        #region - Vars

        private IApplicationConfigService _appConfigService;

        #endregion

        #endregion

        #region Public

        #region - Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="PredefinedConnectionDescriptor" /> class.
        /// </summary>
        /// <param name="appConfigService">The app config service.</param>
        public PredefinedConnectionDescriptor( IApplicationConfigService appConfigService )
            : base( 0 )
        {
            Guard.ArgumentNotNull( appConfigService, "appConfigService" );
            this._appConfigService = appConfigService;
        }

        #endregion

        #endregion

        #region DefaultConnectionDescriptor Members

        /// <summary>
        /// Gets the description for the custom connection.
        /// </summary>
        /// <param name="connectionInfo">The connection info.</param>
        /// <param name="connectionSettings">The connection settings.</param>
        /// <returns>
        /// The description for the custom connection or <c>null</c>.
        /// </returns>
        protected override string GetDescriptionForCustomConnection( IConnectionInfo connectionInfo, ConnectionSettings connectionSettings )
        {
            var predefinedConnectionSettings = connectionSettings as PredefinedConnectionSettings;
            if ( predefinedConnectionSettings != null && !String.IsNullOrWhiteSpace( predefinedConnectionSettings.ConnectionName ) )
            {
                PredefinedConnectionData[] predefinedConnections;
                if ( this._appConfigService.TryGetPredefinedConnections( connectionInfo.AppConfigPath, out predefinedConnections ) )
                {

                    var predefinedConnection = predefinedConnections.FirstOrDefault( e => e.Name == predefinedConnectionSettings.ConnectionName );
                    IDatabaseInfo databaseInfo;
                    if ( predefinedConnection == null )
                        return String.Format( "No such connection named '{0}' !", predefinedConnectionSettings.ConnectionName );
                    else if ( null != ( databaseInfo = connectionInfo.DatabaseInfo ) )
                    {
                        // the database info already provides a GetDatabaseDescription() method.
                        // => we temporarily change the custom connection string,
                        //    to be able to use it and revert our changes afterwards.

                        var oldConnectionString = databaseInfo.CustomCxString;
                        try
                        {
                            databaseInfo.CustomCxString = predefinedConnection.ConnectionString;
                            return databaseInfo.GetDatabaseDescription( );
                        }
                        finally
                        {
                            databaseInfo.CustomCxString = oldConnectionString;
                        }
                    }
                }
            }
            return base.GetDescriptionForCustomConnection( connectionInfo, connectionSettings );
        }
        /// <summary>
        /// Determines whether this instance is able to describe the specified connection.
        /// </summary>
        /// <param name="connectionInfo">The connection info.</param>
        /// <param name="driverSettings">The driver settings.</param>
        /// <returns>
        ///   <c>true</c> if this instance is able to describe the specified connection; otherwise, <c>false</c>.
        /// </returns>
        public override bool CanDescribe( IConnectionInfo connectionInfo, DriverSettings driverSettings )
        {
            return base.CanDescribe( connectionInfo, driverSettings )
                    && driverSettings != null && driverSettings.Connection is PredefinedConnectionSettings
                    && connectionInfo.AppConfigPath != null;
        }


        #endregion
    }
}
